﻿//
//                                                                                 (C) SocketCoder.Com 
// Note: This Project is just some simple samples, if you are looking for a production solution Visit 
// SocketCoder.Com to Buy The Full WCS Web Conferencing Solution Source Code. 
//
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Collections;
using System.Windows.Forms;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;

namespace SocketCoder
{
    public class SocketCoderVoiceServer
    {
        static ArrayList ClientsList = new ArrayList();
        static Socket Listener_Socket;
        static SocketCoderClient Newclient;

        // (1) Establish The Server
        public string Start_A_Server_On(int Port)
        {
            try
            {

                Listener_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                Listener_Socket.Bind(new IPEndPoint(IPAddress.Any, Port));
                Listener_Socket.Listen(-1);

                Listener_Socket.BeginAccept(new AsyncCallback(EndAccept), Listener_Socket);

                return ("Listening On Port: "+ Port + "... Started");

            }
            catch (Exception ex) { return ex.Message; }
        }
        public string ShutDown()
        {
            try
            {
                Listener_Socket.Close();
                GC.Collect();
                GC.WaitForPendingFinalizers();
                return ("Shuted down ...");
            }
            catch (Exception ex) { return (ex.Message); }

        }
        // (2) Accept Clients Conncetion
        private static void EndAccept(IAsyncResult ar)
        {
            try
            {
                Listener_Socket = (Socket)ar.AsyncState;
                AddClient(Listener_Socket.EndAccept(ar));
                Listener_Socket.BeginAccept(new AsyncCallback(EndAccept), Listener_Socket);
            }
            catch (Exception) { }
        }

        // (3) Create a Socket for Each Client and add his Socket to The ArrayList 
        private static void AddClient(Socket sockClient)
        {
            Newclient = new SocketCoderClient(sockClient);

            ClientsList.Add(Newclient);

            // client.Sock.RemoteEndPoint - " has joined the room"
            Newclient.SetupRecieveCallback();
        }

        // (4) Send The Recieved Data to All Clients in The Room
        private static void OnRecievedData(IAsyncResult ar)
        {
            SocketCoderClient client = null;

            try
            {
                client = (SocketCoderClient)ar.AsyncState;

                byte[] aryRet = client.GetRecievedData(ar);


                if (aryRet.Length < 1)
                {
                    // client.Sock.RemoteEndPoint - "has left the room"
                    client.ReadOnlySocket.Close();
                    ClientsList.Remove(client);
                    return;
                }
                foreach (SocketCoderClient clientSend in ClientsList)
                {
                    if (client != clientSend)
                        try
                        {
                            clientSend.ReadOnlySocket.NoDelay = true;
                            clientSend.ReadOnlySocket.Send(aryRet);
                        }
                        catch
                        {
                            clientSend.ReadOnlySocket.Close();
                            ClientsList.Remove(client);
                            return;
                        }
                }
            }
            catch { }
            finally
            {
                if (client != null) 
                client.SetupRecieveCallback();
            }
        }

        internal class SocketCoderClient
        {
            // To create a new socket for each client 

            private Socket New_Socket;
            private byte[] buffer = null;

            public SocketCoderClient(Socket PassedSock)
            {
                New_Socket = PassedSock;
                New_Socket.NoDelay = true;
            }

            public Socket ReadOnlySocket
            {
                get { return New_Socket; }
            }

            public void SetupRecieveCallback()
            {
                try
                {
                    buffer = new byte[95824];
                    AsyncCallback recieveData = new AsyncCallback(SocketCoderVoiceServer.OnRecievedData);
                    New_Socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, recieveData, this);
                }
                catch (Exception)
                {
                }
            }
            public  byte[] GetRecievedData(IAsyncResult ar)
            {
                int nBytesRec = 0;
                try
                {
                    nBytesRec = New_Socket.EndReceive(ar);
                }
                catch { }
                byte[] byReturn = new byte[nBytesRec];
                Array.Copy(buffer, byReturn, nBytesRec);
                return byReturn;
            }
        }

    }
}
